package com.onesports.intelligent.k12.polarlight.service.wx;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.onesports.framework.kit.common.util.ParamUtils;
import com.onesports.framework.kit.common.util.TimeUtils;
import com.onesports.intelligent.k12.polarlight.annotation.DistributedLock;
import com.onesports.intelligent.k12.polarlight.common.domain.entity.BaseEntity;
import com.onesports.intelligent.k12.polarlight.common.errors.exceptions.BusinessException;
import com.onesports.intelligent.k12.polarlight.common.utils.Assert;
import com.onesports.intelligent.k12.polarlight.common.utils.DateUtils;
import com.onesports.intelligent.k12.polarlight.constant.LockConstants;
import com.onesports.intelligent.k12.polarlight.domain.dto.student.StuSpellClassDTO;
import com.onesports.intelligent.k12.polarlight.domain.entity.course.*;
import com.onesports.intelligent.k12.polarlight.domain.entity.market.Orders;
import com.onesports.intelligent.k12.polarlight.domain.entity.student.StudentAttendance;
import com.onesports.intelligent.k12.polarlight.domain.entity.sys.Config;
import com.onesports.intelligent.k12.polarlight.domain.entity.sys.WxUserPurse;
import com.onesports.intelligent.k12.polarlight.domain.vo.cls.SellClaRuleInfoVO;
import com.onesports.intelligent.k12.polarlight.enums.ClassInfoStatusEnum;
import com.onesports.intelligent.k12.polarlight.enums.PeriodStatusEnum;
import com.onesports.intelligent.k12.polarlight.enums.ScheduleDetailStatusEnum;
import com.onesports.intelligent.k12.polarlight.enums.SysConfigTypeEnum;
import com.onesports.intelligent.k12.polarlight.security.SecurityUtils;
import com.onesports.intelligent.k12.polarlight.service.campus.OrganizationCampusService;
import com.onesports.intelligent.k12.polarlight.service.course.ClassStudentScheduleDetailService;
import com.onesports.intelligent.k12.polarlight.service.course.CourseScheduleDetailService;
import com.onesports.intelligent.k12.polarlight.service.course.SpellingClassDetailService;
import com.onesports.intelligent.k12.polarlight.service.course.SpellingClassPeriodService;
import com.onesports.intelligent.k12.polarlight.service.grade.ClassInfoService;
import com.onesports.intelligent.k12.polarlight.service.order.OrderService;
import com.onesports.intelligent.k12.polarlight.service.student.ClassStudentService;
import com.onesports.intelligent.k12.polarlight.service.student.StudentAttendanceService;
import com.onesports.intelligent.k12.polarlight.service.sys.ConfigService;
import com.onesports.intelligent.k12.polarlight.util.NoUtil;
import com.onesports.intelligent.k12.polarlight.util.StrUtils;
import jodd.util.StringUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.time.Instant;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author Wsy
 **/
@Service
@RequiredArgsConstructor
@Slf4j
public class SpellClassService {

    private final ClassInfoService classInfoService;
    private final ClassStudentService classStudentService;
    private final WxUserPurseService wxUserPurseService;
    private final OrderService orderService;
    private final SpellingClassPeriodService spellingClassPeriodService;
    private final StudentAttendanceService studentAttendanceService;
    private final CourseScheduleDetailService courseScheduleDetailService;
    private final ConfigService configService;
    private final OrganizationCampusService organizationCampusService;
    private final ClassStudentScheduleDetailService classStudentScheduleDetailService;
    private final SpellingClassDetailService spellingClassDetailService;


    /**
     * 拼班添加学员
     *
     * @param dto 入参
     * @return Boolean
     */
    @DistributedLock(value = LockConstants.LOCK_SPELL_ADD_STU, keys = "#dto", leaseTime = 60)
    @Transactional(rollbackFor = Exception.class)
    public Boolean addStu(StuSpellClassDTO dto) {
        boolean flag = true;
        Date date = new Date();
        List<StuSpellClassDTO.Stu> stuInfo = dto.getStuInfo();
        dto.setWxUserId(SecurityUtils.getAccountId());
        //校验班级状态是否可进行添加学员操作
        ClassInfo classInfo = this.checkClass(dto.getClassId());
        //校验是否添加了重复的学员
        this.checkStuRepeat(dto.getStuInfo(), classInfo.getId());
        //获取班级拼班规则以及课价
        SellClaRuleInfoVO info = this.classInfoService.spellClaRuleByClaId(dto.getClassId());
        //获取最终可添加的学员
        //获取当前班级学员数量(是之前添加到班级的学员)
        List<ClassStudent> classStudents = this.classStudentService.currentStu(classInfo.getId(), null);
        Integer currentStuNum = classStudents.size();
        //校验人数是否超过拼班人数上限(这边的学员是要新添加进来的学员)
        this.checkClassStuNum(info, currentStuNum, dto.getStuInfo());
        //校验家长余额是否充足
        List<StuSpellClassDTO.Stu> studentList = this.checkBalance(dto.getWxUserId(), info.getPrice(), stuInfo);
        //不可添加的学员
        List<StuSpellClassDTO.Stu> unStuList = studentList.stream().filter(f -> f.getIsNotice().equals(Boolean.TRUE)).collect(Collectors.toList());
        //可添加的学员
        stuInfo = studentList.stream().filter(f -> f.getIsNotice().equals(Boolean.FALSE)).collect(Collectors.toList());

        if (ParamUtils.isNotEmpty(unStuList)) {
            if (ParamUtils.isNotEmpty(stuInfo)) {
                flag = false;
            } else {
                return false;
            }
        }

        //冻结金额(创建订单)
        //获取订单冻结对应的课表详情
        //最新的课表详情id
        String scheduleDetailId = this.getScheduleDetailId(date, classInfo);
        if (ParamUtils.isEmpty(scheduleDetailId)) {
            throw new BusinessException("本周期无课表了,不支持加入拼班");
        }
        //订单表的是否首次拼班的标识
        boolean isFirst = false;
        if (classInfo.getClassStatus().equals(ClassInfoStatusEnum.IN_CLASS.getValue())) {
            isFirst = true;
        }
        this.createOrder(dto.getClassId(), stuInfo, scheduleDetailId, isFirst);
        //添加到班级学员并计算班级已拼学员数（新学员添加进去并重新计算人数）
        List<ClassStudent> newAddStudents = this.addClassStudent(classInfo, stuInfo, scheduleDetailId);
        //添加学员考勤并计算该时段应到人数：保存课表详情以及班级课表应到人数
        CourseScheduleDetail courseScheduleDetail = this.courseScheduleDetailService.getById(scheduleDetailId);
        SpellingClassPeriod period = this.spellingClassPeriodService.period(dto.getClassId(), courseScheduleDetail.getId());
        this.addStudentAttendance(stuInfo, newAddStudents, classInfo, courseScheduleDetail, period);
        //记录班级学员课表
        List<String> classStudentIds = newAddStudents.stream().map(BaseEntity::getId).collect(Collectors.toList());
        this.stuScheduleDetail(classStudentIds, courseScheduleDetail, classInfo.getId());
        //校验人数是否满足条件确认支付
        if (Boolean.FALSE.equals(this.checkStuNum(classStudents, stuInfo.size(), info, date, classInfo, courseScheduleDetail, period))) {
            //未拼班成功调用的方法
            //操作课表详情
            this.courseScheduleDetailService.updateById(courseScheduleDetail);
            //操作班级课表
            this.spellingClassPeriodService.updateById(period);
            //操作班级
            this.classInfoService.updateById(classInfo);
        }
        return flag;
    }

    private void checkStuRepeat(List<StuSpellClassDTO.Stu> stuInfo, String id) {
        List<String> stuIds = stuInfo.stream().map(StuSpellClassDTO.Stu::getStudentId).collect(Collectors.toList());
        List<ClassStudent> classStudents = this.classStudentService.currentStu(id, stuIds);
        if (ParamUtils.isNotEmpty(classStudents)) {
            throw new BusinessException("不可添加重复学员");
        }
    }

    /**
     * 记录班级学员课表
     *
     * @param classStudentIds      班级学员ids
     * @param courseScheduleDetail 最新首次课课表详情
     * @param classId              班级id
     */
    public void stuScheduleDetail(List<String> classStudentIds, CourseScheduleDetail courseScheduleDetail, String classId) {
        //获取下次课
        SpellingClassPeriod earliestCurrentPeriod = this.spellingClassPeriodService.getEarliestCurrentPeriod(classId, courseScheduleDetail.getCourseDate());
        List<ClassStudentScheduleDetail> details = classStudentIds.stream().map(i -> {
            ClassStudentScheduleDetail detail = new ClassStudentScheduleDetail();
            detail.setScheduleDetailId(courseScheduleDetail.getId());
            detail.setNextScheduleDetailId(earliestCurrentPeriod != null ? earliestCurrentPeriod.getCourseScheduleDetailId() : null);
            detail.setClassStudentId(i);
            return detail;
        }).collect(Collectors.toList());
        this.classStudentScheduleDetailService.saveBatch(details);
    }


    /**
     * 获取冻结订单对应的课表详情
     *
     * @param date      当前日期
     * @param classInfo 班级信息
     * @return String
     */
    public String getScheduleDetailId(Date date, ClassInfo classInfo) {
        String id = null;
        //根据班级id获取班级时段
        Date currentDate = TimeUtils.toDate(TimeUtils.toText(date, TimeUtils.DATE_FORMAT), TimeUtils.DATE_FORMAT);
        Date currentTime = TimeUtils.toDate(TimeUtils.toText(date, DateUtils.HH_MM), DateUtils.HH_MM);
        SpellingClassPeriod earliestPeriod = this.spellingClassPeriodService.getEarliestCurrentCanUsePeriod(classInfo.getId(), currentDate);
        if (earliestPeriod != null) {
            id = earliestPeriod.getCourseScheduleDetailId();
        }
        //把早于等于当天的时段变为过期
        List<SpellingClassPeriod> beforeCurrentPeriod = this.spellingClassPeriodService.getBeforeCurrentPeriod(classInfo.getId(), currentDate, currentTime);
        if (ParamUtils.isNotEmpty(beforeCurrentPeriod)) {
            beforeCurrentPeriod.forEach(i -> i.setStatus(PeriodStatusEnum.EXPIRED.getValue()));
            this.spellingClassPeriodService.updateBatchById(beforeCurrentPeriod);
        }
        return id;
    }


    /**
     * 校验人数是否满足条件确认支付
     *
     * @param classStudents 当前学员
     * @param addStuNum     需添加学员数
     * @param info          拼班规则信息
     * @param date          当前日期
     * @param classInfo     班级信息
     * @param period        首次课拼班时段
     */
    private Boolean checkStuNum(List<ClassStudent> classStudents, Integer addStuNum, SellClaRuleInfoVO info,
                                Date date, ClassInfo classInfo, CourseScheduleDetail scheduleDetail, SpellingClassPeriod period) {
        //是否拼成标识
        boolean flag = false;
        //数量大于最低人数要求且当前时间大于等于拼班时间发起后的X小时或者数量等于人数上限且班级状态为拼班中 更改班级状态为拼班成功/课表状态为待考勤
        if (classInfo.getClassStatus().equals(ClassInfoStatusEnum.IN_CLASS.getValue())) {
            //获取配置
            Config config = this.configService.getConfig(SysConfigTypeEnum.A.getValue());
            //当前学员数
            int stuNum = classStudents.size() + addStuNum;
            //计算分钟数
            int minute = Integer.parseInt(config.getValue()) * 60;
            Date conditionDate = DateUtils.addMinuteToDate(minute, Date.from(classInfo.getCreatedDate()), DateUtils.YYYY_MM_DD_HH_MM_SS);

            if ((info.getMaxNum() > stuNum && stuNum >= info.getMinNum() && !date.before(conditionDate)) || info.getMaxNum() == stuNum) {

                //拼班成功的操作
                this.spellSuccessOpt(null, null, classStudents, classInfo, scheduleDetail, date, period);
                flag = true;

            }
        }
        return flag;
    }


    /**
     * 拼班成功的操作
     *
     * @param classStudents  班级下的所有学员
     * @param classInfo      班级信息
     * @param scheduleDetail 大于当前日期的最早有效课表详情信息
     * @param date           当前日期
     * @param period         大于当前日期的最早有效课表详情对应的拼班时段信息
     */
    public void spellSuccessOpt(String optBy, Instant now, List<ClassStudent> classStudents, ClassInfo classInfo, CourseScheduleDetail scheduleDetail, Date date, SpellingClassPeriod period) {
        if (ParamUtils.isNotEmpty(classStudents)) {

            //更改班级首次课课表id
            SpellingClassDetails spellingClassDetails = this.spellingClassDetailService.selectByClassId(classInfo.getId());
            spellingClassDetails.setCourseScheduleDetailId(scheduleDetail.getId());
            if (ParamUtils.isNotEmpty(optBy)) {
                spellingClassDetails.setLastModifiedBy(optBy);
                spellingClassDetails.setLastModifiedDate(now);
                scheduleDetail.setLastModifiedBy(optBy);
                scheduleDetail.setLastModifiedDate(now);
                period.setLastModifiedBy(optBy);
                period.setLastModifiedDate(now);
            }
            this.spellingClassDetailService.updateById(spellingClassDetails);
            //更改班级学员的首节课课表id
            classStudents.forEach(i -> {
                i.setScheduleDetailId(scheduleDetail.getId());
                if (ParamUtils.isNotEmpty(optBy)) {
                    i.setLastModifiedBy(optBy);
                    i.setLastModifiedDate(now);
                }
            });
            this.classStudentService.updateBatchById(classStudents);

            //原来的班级学员信息
            List<String> oldClassStudentIds = classStudents.stream().map(BaseEntity::getId).collect(Collectors.toList());
            List<StudentAttendance> list = this.studentAttendanceService.list(new LambdaQueryWrapper<StudentAttendance>()
                    .in(StudentAttendance::getClassStudentId, oldClassStudentIds));
            //变更前的考勤课表
            List<String> scheduleDetailIds = list.stream().map(StudentAttendance::getScheduleDetailId).distinct().collect(Collectors.toList());
            log.info("拼班添加学员拼班成功调用需过期的班级课表：{}, 当前时间：{}", scheduleDetailIds, new Date());
            this.spellingClassPeriodService.update(new UpdateWrapper<SpellingClassPeriod>()
                    .in("course_schedule_detail_id", scheduleDetailIds)
                    .set("status", PeriodStatusEnum.EXPIRED.getValue())
                    .set("class_attendance_status", ScheduleDetailStatusEnum.CANCEL.getValue())
                    .set(ParamUtils.isNotEmpty(optBy), "last_modified_by", optBy)
                    .set(ParamUtils.isNotEmpty(optBy), "last_modified_date", now));

            //变更之前添加的时段应到人数为0
            List<CourseScheduleDetail> details = this.courseScheduleDetailService.listByIds(scheduleDetailIds);
            details.forEach(i -> {
                i.setDueNum(0);
                if (ParamUtils.isNotEmpty(optBy)) {
                    i.setLastModifiedBy(optBy);
                    i.setLastModifiedDate(now);
                }
            });
            this.courseScheduleDetailService.updateBatchById(details);

            //变更原来的班级课表应到人数
            List<SpellingClassPeriod> periods = this.spellingClassPeriodService.periods(classInfo.getId(), scheduleDetailIds);
            periods.forEach(i -> {
                i.setDueNum(0);
                if (ParamUtils.isNotEmpty(optBy)) {
                    i.setLastModifiedBy(optBy);
                    i.setLastModifiedDate(now);
                }
            });
            this.spellingClassPeriodService.updateBatchById(periods);

            //变更之前添加学员的考勤课表为新的课表详情id
            list.forEach(i -> {
                i.setScheduleDetailId(scheduleDetail.getId());
                if (ParamUtils.isNotEmpty(optBy)) {
                    i.setLastModifiedBy(optBy);
                    i.setLastModifiedDate(now);
                }
            });
            this.studentAttendanceService.updateBatchById(list);


            //变更学员的这节课和下节课
            List<ClassStudentScheduleDetail> classStudentScheduleDetails = this.classStudentScheduleDetailService.listByClassStudentIds(oldClassStudentIds);
            if (ParamUtils.isNotEmpty(classStudentScheduleDetails)) {
                SpellingClassPeriod earliestCurrentPeriod = this.spellingClassPeriodService.getEarliestCurrentPeriod(classInfo.getId(), scheduleDetail.getCourseDate());
                classStudentScheduleDetails.forEach(i -> {
                    i.setScheduleDetailId(scheduleDetail.getId());
                    i.setNextScheduleDetailId(earliestCurrentPeriod != null ? earliestCurrentPeriod.getCourseScheduleDetailId() : null);
                    if (ParamUtils.isNotEmpty(optBy)) {
                        i.setLastModifiedBy(optBy);
                        i.setLastModifiedDate(now);
                    }
                });
                this.classStudentScheduleDetailService.updateBatchById(classStudentScheduleDetails);
            }
        }

        //更改课表详情的所有当前拼班时段为待考勤
        this.optScheduleDetail(scheduleDetail);

        //更改拼班时段学员应到数量
        period.setDueNum(classInfo.getUseStudentNum());
        this.optPeriod(period);

        classInfo.setClassStatus(ClassInfoStatusEnum.FINISH_CLASS.getValue());
        classInfo.setCompleteTime(date);
        //订单支付
        //获取班级下所有学员的待付款订单
        List<Orders> orders = this.orderService.waitPayByClassId(classInfo.getId());
        orders.forEach(i -> {
            i.setScheduleDetailId(scheduleDetail.getId());
            if (ParamUtils.isNotEmpty(optBy)) {
                i.setLastModifiedBy(optBy);
                i.setLastModifiedDate(now);
            }
            this.orderService.confirm(i, false);
        });
        this.organizationCampusService.addCampusSpellNum(classInfo.getCampusId());
        //操作班级
        this.classInfoService.updateById(classInfo);
    }

    private void optPeriod(SpellingClassPeriod period) {
        this.spellingClassPeriodService.updateById(period);
    }

    public void optScheduleDetail(CourseScheduleDetail scheduleDetail) {
        log.info("===============课程日期：{}", scheduleDetail.getCourseDate());
        //更改大于等于课程日期、等于拼班选择时段的课表详情状态  ： 未拼班->待考勤  、应到人数 此处的课程日期是大于当天的首次课的日期
        //获取大于等于课程日期、等于拼班选择时段的课表详情
        List<CourseScheduleDetail> geScheduleDetails = this.courseScheduleDetailService.geScheduleDetail(scheduleDetail);
        log.info("===============大于等于课程日期数据：{}", geScheduleDetails);
        if (ParamUtils.isNotEmpty(geScheduleDetails)) {
            geScheduleDetails.forEach(i -> {
                i.setStatus(ScheduleDetailStatusEnum.WAIT_ATTENDANCE.getValue());
                //添加考勤会添加数量  所以这边不加
                if (i.getId().equals(scheduleDetail.getId())){
                    i.setDueNum(scheduleDetail.getDueNum());
                }
                if (ParamUtils.isNotEmpty(scheduleDetail.getLastModifiedBy())) {
                    i.setLastModifiedBy(scheduleDetail.getLastModifiedBy());
                    i.setLastModifiedDate(scheduleDetail.getLastModifiedDate());
                }
                this.courseScheduleDetailService.updateById(i);
            });
        }
        //更改小于课程日期、等于拼班选择时段的课表详情状态为作废，因为时间已经过去了，无法拼班
        log.info("===============小于课程日期数据：{}", geScheduleDetails);
        List<CourseScheduleDetail> ltScheduleDetails = this.courseScheduleDetailService.ltScheduleDetail(scheduleDetail);
        if (ParamUtils.isNotEmpty(ltScheduleDetails)) {
            ltScheduleDetails.forEach(i -> {
                i.setStatus(ScheduleDetailStatusEnum.CANCEL.getValue());
                if (ParamUtils.isNotEmpty(scheduleDetail.getLastModifiedBy())) {
                    i.setLastModifiedBy(scheduleDetail.getLastModifiedBy());
                    i.setLastModifiedDate(scheduleDetail.getLastModifiedDate());
                }
                this.courseScheduleDetailService.updateById(i);
            });
        }
    }


    /**
     * 添加学员考勤并计算该时段应到人数
     *
     * @param stuList       学员入参
     * @param classStudents 班级学员
     * @param classInfo     班级信息
     */
    public void addStudentAttendance(List<StuSpellClassDTO.Stu> stuList, List<ClassStudent> classStudents,
                                     ClassInfo classInfo, CourseScheduleDetail scheduleDetail, SpellingClassPeriod period) {
        Map<String, String> stuMap = stuList.stream().collect(Collectors.toMap(StuSpellClassDTO.Stu::getStudentId, StuSpellClassDTO.Stu::getOrderId));
        List<StudentAttendance> studentAttendances = classStudents.stream().map(i -> {
            StudentAttendance attendance = new StudentAttendance();
            attendance.setCoachId(classInfo.getCoachId())
                    .setOrderId(stuMap.get(i.getStudentId()))
                    .setClassStudentId(i.getId())
                    .setScheduleDetailId(scheduleDetail.getId())
                    .setAttendanceCode(NoUtil.code());
            return attendance;
        }).collect(Collectors.toList());

        this.studentAttendanceService.saveBatch(studentAttendances);

        //设置当前拼成课表的应到人数
        scheduleDetail.setDueNum(scheduleDetail.getDueNum() + studentAttendances.size());

        //设置当前班级课表的应到人数
        period.setDueNum(period.getDueNum() + studentAttendances.size());


    }

    public void createOrder(String classId, List<StuSpellClassDTO.Stu> stuList, String scheduleDetailId, Boolean first) {
        stuList.forEach(i -> {
            Orders order = this.orderService.createOrder(classId, i.getStudentId(), scheduleDetailId, first);
            i.setOrderId(order.getId());
        });
    }

    /**
     * 添加到班级学员并计算班级已拼学员数
     *
     * @param classInfo 班级信息
     * @param stuList   学员信息
     * @return List<ClassStudent>
     */
    private List<ClassStudent> addClassStudent(ClassInfo classInfo, List<StuSpellClassDTO.Stu> stuList, String scheduleDetailId) {
        //获取总课次
        Integer totalNum = this.spellingClassPeriodService.getTotalNum(classInfo.getId());
        List<ClassStudent> classStudents = stuList.stream().map(i -> {
            ClassStudent classStudent = new ClassStudent();
            classStudent.setStudentId(i.getStudentId());
            classStudent.setClassInfoId(classInfo.getId());
            classStudent.setJoinTime(new Date());
            classStudent.setSort(i.getSort());
            classStudent.setTotalNum(totalNum);
            classStudent.setScheduleDetailId(scheduleDetailId);
            return classStudent;
        }).collect(Collectors.toList());

        this.classStudentService.saveBatch(classStudents);

        //设置班级已拼学员数
        classInfo.setUseStudentNum(classInfo.getUseStudentNum() + classStudents.size());
        return classStudents;
    }


    /**
     * 校验家长余额是否充足
     *
     * @param wxUserId 家长id
     * @param price    课单价
     * @param stuList  学员
     */
    public List<StuSpellClassDTO.Stu> checkBalance(String wxUserId, BigDecimal price, List<StuSpellClassDTO.Stu> stuList) {
        log.info("当前用户：{}", wxUserId);
        WxUserPurse myPurse = this.wxUserPurseService.getMyPurse(wxUserId);
        log.info("当前用户余额：{}", myPurse);
        BigDecimal amount = myPurse.getTotalAmount();
        for (StuSpellClassDTO.Stu stu : stuList) {
            amount = amount.subtract(price);
            if (amount.compareTo(BigDecimal.ZERO) > -1) {
                stu.setIsNotice(false);
            } else {
                stu.setIsNotice(true);
            }
        }
        return stuList;
    }


    /**
     * 校验人数是否超过拼班人数上限
     *
     * @param currentStuNum 当前学员数量
     * @param addStu        需要添加的需要数量
     * @return SellClaRuleInfoVO
     */
    private void checkClassStuNum(SellClaRuleInfoVO info, Integer currentStuNum, List<StuSpellClassDTO.Stu> addStu) {
        //还可添加学员数量 = 需添加学员数 - （班级当前学员数 + 需添加学员数 - 人数上限）
        int canAddNum = addStu.size() - (currentStuNum + addStu.size() - info.getMaxNum());
        if (addStu.size() > canAddNum) {
            throw new BusinessException("您添加学员数量超过拼班最高人数限制，请重新选择。");
        }
//        if (canAddNum >= addStu.size()) {
//            return addStu;
//        } else {
//            return addStu.stream().sorted(Comparator.comparing(StuSpellClassDTO.Stu::getSort)).collect(Collectors.toList()).subList(0, canAddNum);
//        }
    }

    /**
     * 校验班级状态是否可进行添加学员操作
     *
     * @param classId 班级id
     * @return ClassInfo 班级
     */
    private ClassInfo checkClass(String classId) {
        //满足添加学员操作的班级状态：拼班中、拼班完成、开班中
        List<String> status = Arrays.asList(ClassInfoStatusEnum.IN_CLASS.getValue(), ClassInfoStatusEnum.FINISH_CLASS.getValue(), ClassInfoStatusEnum.OPEN_CLASS.getValue());
        ClassInfo classInfo = this.classInfoService.getById(classId);
        Assert.notNull(classInfo, "查无班级，无法加入。");
        Assert.isTrue(status.contains(classInfo.getClassStatus()), "班级当前状态下不可进行添加学员");
        return classInfo;
    }
}
